{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Backend API\n",
    "\n",
    "Wrap the following APIs using Python requests:\n",
    "\n",
    "| Method | URL | Description |\n",
    "| --- | --- | --- |\n",
    "| GET | `http://{{host}}/backend-api/accounts/check` | check account status |\n",
    "| GET | `http://{{host}}/backend-api/models?history_and_training_disabled=false` | get models |\n",
    "| GET | `http://{{host}}/backend-api/settings/beta_features` | get beta features |\n",
    "| GET | `http://{{host}}/public-api/conversation_limit` | get conversation limit(GPT4) |\n",
    "| GET | `http://{{host}}/backend-api/conversations?offset=0&limit=3&order=updated` | get conversation list |\n",
    "| GET | `http://{{host}}/backend-api/conversation/{{conversation_id}}` | get conversation by id |\n",
    "| PATCH | `http://{{host}}/backend-api/conversation/{{conversation_id}}` | clear conversation by id |\n",
    "| POST | `http://{{host}}/backend-api/conversation` | new conversation |\n",
    "| GET | `http://{{host}}/backend-api/shared_conversations?order=created` | get share link |\n",
    "| POST | `http://{{host}}/backend-api/accounts/data_export` | export data send to email |\n",
    "| PATCH | `http://{{host}}/backend-api/conversation/{{conversation_id}}` | change conversation title by id |\n",
    "| POST | `http://{{host}}/backend-api/conversation/gen_title/{{conversation_id}}` | generate conversation title |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup\n",
    "\n",
    "```bash\n",
    "export OPENAI_API_BASE_URL=\"https://ninja.yourdomain.com\"\n",
    "export BACKEND_REVERSE_PROXY=\"https://ninja.yourdomain.com/backend-api\"\n",
    "export OPENAI_ACCESS_TOKEN=\"your_openai_access_token\"\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initialize"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os, json, requests, uuid\n",
    "from pprint import pprint\n",
    "from typing import Union\n",
    "# set default values\n",
    "base_url = os.getenv(\"OPENAI_API_BASE_URL\")\n",
    "backend_url = os.getenv(\"OPENAI_API_BACKEND_URL\")\n",
    "access_token = os.getenv(\"OPENAI_API_KEY\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## API Wrapper"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Check account status"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'account_plan': {'account_user_role': 'account-owner',\n",
      "                  'has_customer_object': False,\n",
      "                  'is_paid_subscription_active': False,\n",
      "                  'subscription_expires_at_timestamp': 1702560866,\n",
      "                  'subscription_plan': 'chatgptfreeplan',\n",
      "                  'was_paid_customer': True},\n",
      " 'features': ['chat_preferences_available',\n",
      "              'shareable_links',\n",
      "              'allow_url_thread_creation',\n",
      "              'disable_team_upgrade_ui',\n",
      "              'user_settings_announcements',\n",
      "              'targeted_replies',\n",
      "              'bizmo_settings',\n",
      "              'arkose_gpt_35_experiment',\n",
      "              'breeze_available',\n",
      "              'gizmo_live',\n",
      "              'privacy_policy_nov_2023',\n",
      "              'starter_prompts',\n",
      "              'conversation_bot_arkose',\n",
      "              'new_plugin_oauth_endpoint',\n",
      "              'gizmo_ui',\n",
      "              'check_age_verification',\n",
      "              'invite_referral',\n",
      "              'arkose_enabled'],\n",
      " 'user_country': 'KR'}\n"
     ]
    }
   ],
   "source": [
    "def get_account_status(backend_url:str, access_token:str):\n",
    "    \"\"\"Get account status from backend-api\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "    \n",
    "    Returns:\n",
    "        dict: account status\n",
    "    \n",
    "    Rest API:\n",
    "        ### check account status\n",
    "        GET http://{{host}}/backend-api/accounts/check\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"accounts/check\")\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.get(url, headers=headers)\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "resp = get_account_status(backend_url, access_token)\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['gpt_3.5']\n",
      "{'categories': [{'category': 'gpt_3.5',\n",
      "                 'code_interpreter_model': 'text-davinci-002-render-sha-code-interpreter',\n",
      "                 'default_model': 'text-davinci-002-render-sha',\n",
      "                 'human_category_name': 'GPT-3.5',\n",
      "                 'plugins_model': 'text-davinci-002-render-sha-plugins',\n",
      "                 'subscription_level': 'free'}],\n",
      " 'models': [{'capabilities': {},\n",
      "             'description': 'Our fastest model, great for most everyday tasks.',\n",
      "             'max_tokens': 8191,\n",
      "             'product_features': {},\n",
      "             'slug': 'text-davinci-002-render-sha',\n",
      "             'tags': ['gpt3.5'],\n",
      "             'title': 'Default (GPT-3.5)'}]}\n"
     ]
    }
   ],
   "source": [
    "def get_models(backend_url:str, access_token:str, history_and_training_disabled:bool=False):\n",
    "    \"\"\"Get models from backend-api\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        history_and_training_disabled (bool, optional): history and training disabled. Defaults to False.\n",
    "    \n",
    "    Returns:\n",
    "        dict: models\n",
    "    \n",
    "    Rest API:\n",
    "        ### get models\n",
    "        GET http://{{host}}/backend-api/models?history_and_training_disabled=false\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"models\")\n",
    "    params = {\n",
    "        \"history_and_training_disabled\": history_and_training_disabled\n",
    "    }\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.get(url, params=params, headers=headers)\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "resp = get_models(backend_url, access_token)\n",
    "print([model['category'] for model in resp[\"categories\"]])\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get Beta Features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'browsing': True,\n",
      " 'code_interpreter': False,\n",
      " 'dalle': False,\n",
      " 'plugins': False,\n",
      " 'sunshine': False,\n",
      " 'workspace_gpt_custom_actions': False}\n"
     ]
    }
   ],
   "source": [
    "def get_beta_features(backend_url:str, access_token:str):\n",
    "    \"\"\"Get beta features from backend-api\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "    \n",
    "    Returns:\n",
    "        dict: beta features\n",
    "    \n",
    "    Rest API:\n",
    "        ### get beta features\n",
    "        GET http://{{host}}/backend-api/settings/beta_features\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"settings/beta_features\")\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.get(url, headers=headers)\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "pprint(get_beta_features(backend_url, access_token))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get Chat List"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'conversation_id': 'be06ea4d-a482-49ee-93a8-3dbb68b39f74',\n",
      "  'title': 'User Request: Summarize Conversation'}]\n",
      "{'has_missing_conversations': False,\n",
      " 'items': [{'conversation_template_id': None,\n",
      "            'create_time': '2023-12-22T03:46:06.392671+00:00',\n",
      "            'current_node': None,\n",
      "            'gizmo_id': None,\n",
      "            'id': 'be06ea4d-a482-49ee-93a8-3dbb68b39f74',\n",
      "            'is_archived': False,\n",
      "            'mapping': None,\n",
      "            'title': 'User Request: Summarize Conversation',\n",
      "            'update_time': '2023-12-22T03:54:24.776292+00:00',\n",
      "            'workspace_id': None}],\n",
      " 'limit': 1,\n",
      " 'offset': 0,\n",
      " 'total': 1635}\n"
     ]
    }
   ],
   "source": [
    "def get_chat_list( backend_url:str, access_token:str\n",
    "                 , offset:int=0, limit:Union[int, None]=None, order:str=\"updated\"):\n",
    "    \"\"\"Get chat list from backend-api\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        offset (int, optional): start index. Defaults to 0.\n",
    "        limit (int, optional): max number of chat. Defaults to 3.\n",
    "        order (str, optional): order by. Defaults to \"updated\".\n",
    "    \n",
    "    Returns:\n",
    "        dict: chat list\n",
    "    \n",
    "    Rest API:\n",
    "        ### get conversation list\n",
    "        GET http://{{host}}/backend-api/conversations?offset=0&limit=3&order=updated\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"conversations\")\n",
    "    params = {\n",
    "        \"offset\": offset,\n",
    "        \"limit\": limit,\n",
    "        \"order\": order\n",
    "    }\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.get(url, params=params, headers=headers)\n",
    "    return response.json()\n",
    "## example\n",
    "resp = get_chat_list(backend_url, access_token, limit=1)\n",
    "pprint([{'conversation_id':item['id'],'title': item['title']} for item in resp['items']])\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Chat Completion"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def chat_completion( backend_url:str, access_token:str\n",
    "                   , prompt:str\n",
    "                   , current_message_id:str\n",
    "                   , parent_message_id:str\n",
    "                   , conversation_id:Union[str, None]=None\n",
    "                   , model:str=\"text-davinci-002-render-sha\"\n",
    "                   , history_and_training_disabled:bool=False):\n",
    "    \"\"\"chat completion(create or edit)\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        prompt (str): prompt\n",
    "        current_message_id (str): current message id. You can use uuid.uuid4() to generate one.\n",
    "        parent_message_id (str): parent message id.\n",
    "        conversation_id (str, optional): conversation id. Defaults to None.\n",
    "        model (str, optional): model. Defaults to \"text-davinci-002-render-sha\".\n",
    "        history_and_training_disabled (bool, optional): disable history record in the website. Defaults to False.\n",
    "    \n",
    "    Returns:\n",
    "        dict: chat\n",
    "    \n",
    "    Rest API:\n",
    "        ### new conversation\n",
    "        POST http://{{host}}/backend-api/conversation\n",
    "        Authorization: {{bearer_token}}\n",
    "        Content-Type: application/json\n",
    "        Accept: text/event-stream\n",
    "    \n",
    "    {\n",
    "        \"action\": \"next\",\n",
    "        \"messages\": [\n",
    "            {\n",
    "            \"id\": \"{{$guid}}\",\n",
    "            \"author\": {\n",
    "                \"role\": \"user\"\n",
    "            },\n",
    "            \"content\": {\n",
    "                \"content_type\": \"text\",\n",
    "                \"parts\": [\n",
    "                \"new conversation\"\n",
    "                ]\n",
    "            },\n",
    "            \"metadata\": {}\n",
    "            }\n",
    "        ],\n",
    "        \"model\": \"text-davinci-002-render-sha-mobile\",\n",
    "        \"parent_message_id\": \"{{$guid}}\",\n",
    "        \"timezone_offset_min\": -480,\n",
    "        \"history_and_training_disabled\": false\n",
    "    }\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"conversation\")\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}',\n",
    "        'Accept': 'text/event-stream'\n",
    "    }\n",
    "    messages = [\n",
    "        {\n",
    "            \"id\": current_message_id,\n",
    "            \"author\": {\"role\": \"user\"},\n",
    "            \"content\": {\"content_type\": \"text\", \"parts\": [prompt]},\n",
    "        },\n",
    "    ]\n",
    "    data = {\n",
    "        \"action\": \"next\",\n",
    "        \"messages\": messages,\n",
    "        \"conversation_id\": conversation_id,\n",
    "        \"parent_message_id\": parent_message_id,\n",
    "        \"model\": model,\n",
    "        \"history_and_training_disabled\": history_and_training_disabled,\n",
    "    }\n",
    "    response = requests.post(url, headers=headers, data=json.dumps(data))\n",
    "    resps = response.text.split(\"data:\")[:-1] # the last one is [DONE]\n",
    "    return [json.loads(resp) for resp in resps if resp.strip() != \"\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "prompt: hello\n",
      "response: Hello! How can I assist you today?\n",
      "prompt: how are you?\n",
      "response: Hello! I'm just a computer program, so I don't have feelings, but I'm here and ready to help you with any questions or information you might need. How can I assist you today?\n",
      "conversation_id: 9edf4b4b-3c43-4002-a666-c8e1493f4935\n",
      "{'conversation_id': '9edf4b4b-3c43-4002-a666-c8e1493f4935',\n",
      " 'is_completion': True,\n",
      " 'message_id': '3a9186f9-1fbc-444a-ab13-9c2f2012de54',\n",
      " 'moderation_response': {'blocked': False,\n",
      "                         'flagged': False,\n",
      "                         'moderation_id': 'modr-8YR2sJrIvr9OemnRoObGCb29GdrOg'}}\n",
      "{'conversation_id': '9edf4b4b-3c43-4002-a666-c8e1493f4935',\n",
      " 'error': None,\n",
      " 'message': {'author': {'metadata': {}, 'name': None, 'role': 'assistant'},\n",
      "             'content': {'content_type': 'text',\n",
      "                         'parts': [\"Hello! I'm just a computer program, so I \"\n",
      "                                   \"don't have feelings, but I'm here and \"\n",
      "                                   'ready to help you with any questions or '\n",
      "                                   'information you might need. How can I '\n",
      "                                   'assist you today?']},\n",
      "             'create_time': 1703217807.904909,\n",
      "             'end_turn': True,\n",
      "             'id': '3fc222d4-b78d-4634-b903-e7de75a54470',\n",
      "             'metadata': {'finish_details': {'stop_tokens': [100260],\n",
      "                                             'type': 'stop'},\n",
      "                          'inline_gizmo_id': None,\n",
      "                          'is_complete': True,\n",
      "                          'message_type': 'next',\n",
      "                          'model_slug': 'text-davinci-002-render-sha',\n",
      "                          'parent_id': '3a9186f9-1fbc-444a-ab13-9c2f2012de54'},\n",
      "             'recipient': 'all',\n",
      "             'status': 'finished_successfully',\n",
      "             'update_time': None,\n",
      "             'weight': 1.0}}\n"
     ]
    }
   ],
   "source": [
    "## Example 1: create chat\n",
    "parent_message_id, current_message_id = str(uuid.uuid4()), str(uuid.uuid4())\n",
    "prompt = \"hello\"\n",
    "resp = chat_completion(backend_url, access_token, prompt,  current_message_id, parent_message_id)\n",
    "conversation_id, message_id = resp[-1]['conversation_id'], resp[-1]['message_id']\n",
    "message = resp[-2]['message']['content']['parts'][0]\n",
    "## Note: you can continue/regenerate the response base on the parent_message_id\n",
    "## Example 2: continue the chat\n",
    "newprompt = \"how are you?\"\n",
    "parent_message_id, current_message_id = message_id, str(uuid.uuid4())\n",
    "newresp = chat_completion(backend_url, access_token, newprompt, parent_message_id, current_message_id, conversation_id)\n",
    "newmessage = newresp[-2]['message']['content']['parts'][0]\n",
    "\n",
    "print(f\"prompt: {prompt}\\nresponse: {message}\\nprompt: {newprompt}\\nresponse: {newmessage}\")\n",
    "print(f\"conversation_id: {conversation_id}\")\n",
    "# The message is too long, so we only print the last two messages here\n",
    "pprint(resp[-1])\n",
    "pprint(newresp[-2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Chat By ID"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'conversation_id': '9edf4b4b-3c43-4002-a666-c8e1493f4935',\n",
      " 'create_time': 1703217806.360512,\n",
      " 'current_node': '3fc222d4-b78d-4634-b903-e7de75a54470',\n",
      " 'is_archived': False,\n",
      " 'mapping': {'3375543a-2b45-4eb3-b325-54307e3d3bf5': {'children': ['bd768a32-0124-418a-864d-146940e8fe4c'],\n",
      "                                                      'id': '3375543a-2b45-4eb3-b325-54307e3d3bf5',\n",
      "                                                      'message': {'author': {'metadata': {},\n",
      "                                                                             'role': 'system'},\n",
      "                                                                  'content': {'content_type': 'text',\n",
      "                                                                              'parts': ['']},\n",
      "                                                                  'end_turn': True,\n",
      "                                                                  'id': '3375543a-2b45-4eb3-b325-54307e3d3bf5',\n",
      "                                                                  'metadata': {},\n",
      "                                                                  'recipient': 'all',\n",
      "                                                                  'status': 'finished_successfully',\n",
      "                                                                  'weight': 0.0},\n",
      "                                                      'parent': 'd701450b-cae3-44d8-8e8c-2ae6e8d18db7'},\n",
      "             '3a9186f9-1fbc-444a-ab13-9c2f2012de54': {'children': ['3fc222d4-b78d-4634-b903-e7de75a54470'],\n",
      "                                                      'id': '3a9186f9-1fbc-444a-ab13-9c2f2012de54',\n",
      "                                                      'message': {'author': {'metadata': {},\n",
      "                                                                             'role': 'user'},\n",
      "                                                                  'content': {'content_type': 'text',\n",
      "                                                                              'parts': ['how '\n",
      "                                                                                        'are '\n",
      "                                                                                        'you?']},\n",
      "                                                                  'create_time': 1703217806.768081,\n",
      "                                                                  'id': '3a9186f9-1fbc-444a-ab13-9c2f2012de54',\n",
      "                                                                  'metadata': {'timestamp_': 'absolute'},\n",
      "                                                                  'recipient': 'all',\n",
      "                                                                  'status': 'finished_successfully',\n",
      "                                                                  'weight': 1.0},\n",
      "                                                      'parent': 'bd768a32-0124-418a-864d-146940e8fe4c'},\n",
      "             '3fc222d4-b78d-4634-b903-e7de75a54470': {'children': [],\n",
      "                                                      'id': '3fc222d4-b78d-4634-b903-e7de75a54470',\n",
      "                                                      'message': {'author': {'metadata': {},\n",
      "                                                                             'role': 'assistant'},\n",
      "                                                                  'content': {'content_type': 'text',\n",
      "                                                                              'parts': ['Hello! '\n",
      "                                                                                        \"I'm \"\n",
      "                                                                                        'just '\n",
      "                                                                                        'a '\n",
      "                                                                                        'computer '\n",
      "                                                                                        'program, '\n",
      "                                                                                        'so '\n",
      "                                                                                        'I '\n",
      "                                                                                        \"don't \"\n",
      "                                                                                        'have '\n",
      "                                                                                        'feelings, '\n",
      "                                                                                        'but '\n",
      "                                                                                        \"I'm \"\n",
      "                                                                                        'here '\n",
      "                                                                                        'and '\n",
      "                                                                                        'ready '\n",
      "                                                                                        'to '\n",
      "                                                                                        'help '\n",
      "                                                                                        'you '\n",
      "                                                                                        'with '\n",
      "                                                                                        'any '\n",
      "                                                                                        'questions '\n",
      "                                                                                        'or '\n",
      "                                                                                        'information '\n",
      "                                                                                        'you '\n",
      "                                                                                        'might '\n",
      "                                                                                        'need. '\n",
      "                                                                                        'How '\n",
      "                                                                                        'can '\n",
      "                                                                                        'I '\n",
      "                                                                                        'assist '\n",
      "                                                                                        'you '\n",
      "                                                                                        'today?']},\n",
      "                                                                  'create_time': 1703217808.782712,\n",
      "                                                                  'end_turn': True,\n",
      "                                                                  'id': '3fc222d4-b78d-4634-b903-e7de75a54470',\n",
      "                                                                  'metadata': {'finish_details': {'stop_tokens': [100260],\n",
      "                                                                                                  'type': 'stop'},\n",
      "                                                                               'is_complete': True,\n",
      "                                                                               'model_slug': 'text-davinci-002-render-sha',\n",
      "                                                                               'parent_id': '3a9186f9-1fbc-444a-ab13-9c2f2012de54',\n",
      "                                                                               'timestamp_': 'absolute'},\n",
      "                                                                  'recipient': 'all',\n",
      "                                                                  'status': 'finished_successfully',\n",
      "                                                                  'weight': 1.0},\n",
      "                                                      'parent': '3a9186f9-1fbc-444a-ab13-9c2f2012de54'},\n",
      "             'bd768a32-0124-418a-864d-146940e8fe4c': {'children': ['3a9186f9-1fbc-444a-ab13-9c2f2012de54'],\n",
      "                                                      'id': 'bd768a32-0124-418a-864d-146940e8fe4c',\n",
      "                                                      'message': {'author': {'metadata': {},\n",
      "                                                                             'role': 'user'},\n",
      "                                                                  'content': {'content_type': 'text',\n",
      "                                                                              'parts': ['hello']},\n",
      "                                                                  'create_time': 1703217806.361237,\n",
      "                                                                  'id': 'bd768a32-0124-418a-864d-146940e8fe4c',\n",
      "                                                                  'metadata': {'timestamp_': 'absolute'},\n",
      "                                                                  'recipient': 'all',\n",
      "                                                                  'status': 'finished_successfully',\n",
      "                                                                  'weight': 1.0},\n",
      "                                                      'parent': '3375543a-2b45-4eb3-b325-54307e3d3bf5'},\n",
      "             'd701450b-cae3-44d8-8e8c-2ae6e8d18db7': {'children': ['3375543a-2b45-4eb3-b325-54307e3d3bf5'],\n",
      "                                                      'id': 'd701450b-cae3-44d8-8e8c-2ae6e8d18db7'}},\n",
      " 'moderation_results': [],\n",
      " 'safe_urls': [],\n",
      " 'title': 'New chat',\n",
      " 'update_time': 1703217808.7853}\n"
     ]
    }
   ],
   "source": [
    "def get_chat_by_id(backend_url:str, access_token:str, conversation_id:str):\n",
    "    \"\"\"Get chat by id from backend-api\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        conversation_id (str): conversation id\n",
    "    \n",
    "    Returns:\n",
    "        dict: chat\n",
    "    \n",
    "    Rest API:\n",
    "        ### get conversation by id\n",
    "        GET http://{{host}}/backend-api/conversation/5ae8355a-82a8-4ded-b0e4-ea5dc11b4a9f\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"conversation\", conversation_id)\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.get(url, headers=headers)\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "chat_list_resp = get_chat_list(backend_url, access_token, limit=1)\n",
    "conversation_id = chat_list_resp['items'][0]['id']\n",
    "resp = get_chat_by_id(backend_url, access_token, conversation_id)\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Delete Chat"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'success': True}\n"
     ]
    }
   ],
   "source": [
    "def delete_chat(backend_url:str, access_token:str, conversation_id:str):\n",
    "    \"\"\"Delete chat by id\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        conversation_id (str): conversation id\n",
    "    \n",
    "    Returns:\n",
    "        dict: response\n",
    "    \n",
    "    Rest API:\n",
    "        ### clear conversation by id\n",
    "        PATCH http://{{host}}/backend-api/conversation/5ae8355a-82a8-4ded-b0e4-ea5dc11b4a9f\n",
    "        Authorization: {{bearer_token}}\n",
    "        Content-Type: application/json\n",
    "\n",
    "        {\n",
    "            \"is_visible\": false\n",
    "        }\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"conversation\", conversation_id)\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    data = {\n",
    "        \"is_visible\": False\n",
    "    }\n",
    "    response = requests.patch(url, headers=headers, data=json.dumps(data))\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "chat_list_resp = get_chat_list(backend_url, access_token, limit=1)\n",
    "conversation_id = chat_list_resp['items'][0]['id']\n",
    "resp = delete_chat(backend_url, access_token, conversation_id)\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get Shared Links"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'has_missing_conversations': False,\n",
      " 'items': [{'conversation_id': '6677a2e1-bb24-45a0-8f81-8609e4a53665',\n",
      "            'conversation_template_id': None,\n",
      "            'create_time': '2023-12-13T17:16:53.407544+00:00',\n",
      "            'current_node': None,\n",
      "            'gizmo_id': None,\n",
      "            'id': '9942703e-0b2b-42b3-aee5-ed0de8335e2d',\n",
      "            'is_archived': None,\n",
      "            'mapping': None,\n",
      "            'title': '物流优化问题解决方案',\n",
      "            'update_time': '2023-12-13T17:17:10+00:00',\n",
      "            'workspace_id': None}],\n",
      " 'limit': 50,\n",
      " 'offset': 0,\n",
      " 'total': 14}\n"
     ]
    }
   ],
   "source": [
    "def get_share_links(backend_url:str, access_token:str, order:str=\"created\"):\n",
    "    \"\"\"Get share links from backend-api\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        order (str, optional): order by. Defaults to \"created\".\n",
    "    \n",
    "    Returns:\n",
    "        dict: share links\n",
    "    \n",
    "    Rest API:\n",
    "        ### get share link\n",
    "        GET http://{{host}}/backend-api/shared_conversations?order=created\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"shared_conversations\")\n",
    "    params = {\n",
    "        \"order\": order\n",
    "    }\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.get(url, params=params, headers=headers)\n",
    "    return response.json()\n",
    "\n",
    "## xample\n",
    "resp = get_share_links(backend_url, access_token)\n",
    "# pprint(resp) # too long, so we only print the first one\n",
    "resp['items'] = resp['items'][:1]\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Edit Chat Title"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'success': True}\n"
     ]
    }
   ],
   "source": [
    "def edit_chat_title(backend_url:str, access_token:str, conversation_id:str, title:str):\n",
    "    \"\"\"Edit chat title by id\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        conversation_id (str): conversation id\n",
    "        title (str): title\n",
    "    \n",
    "    Returns:\n",
    "        dict: response\n",
    "    \n",
    "    Rest API:\n",
    "        ### change conversation title by id\n",
    "        PATCH http://{{host}}/backend-api/conversation/5ae8355a-82a8-4ded-b0e4-ea5dc11b4a9f\n",
    "        Authorization: {{bearer_token}}\n",
    "        Content-Type: application/json\n",
    "\n",
    "        {\n",
    "            \"title\": \"New Test\"\n",
    "        }\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"conversation\", conversation_id)\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    data = {\n",
    "        \"title\": title\n",
    "    }\n",
    "    response = requests.patch(url, headers=headers, data=json.dumps(data))\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "chat_list_resp = get_chat_list(backend_url, access_token, limit=1)\n",
    "conversation_id = chat_list_resp['items'][0]['id']\n",
    "resp = edit_chat_title(backend_url, access_token, conversation_id, \"New Test\")\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generate Chat Title"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'message': 'Conversation be06ea4d-a482-49ee-93a8-3dbb68b39f74 already has '\n",
      "            \"title 'New Test'\"}\n"
     ]
    }
   ],
   "source": [
    "def generate_chat_title(backend_url:str, access_token:str, conversation_id:str, message_id:str):\n",
    "    \"\"\"Generate chat title by id and message id\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "        conversation_id (str): conversation id\n",
    "        message_id (str): message id\n",
    "    \n",
    "    Returns:\n",
    "        dict: response\n",
    "    \n",
    "    Rest API:\n",
    "        ### generate conversation title\n",
    "        POST http://{{host}}/backend-api/conversation/gen_title/5ae8355a-82a8-4ded-b0e4-ea5dc11b4a9f\n",
    "        Authorization: {{bearer_token}}\n",
    "        Content-Type: application/json\n",
    "\n",
    "        {\n",
    "            \"message_id\": \"1646facc-08a6-465f-ba08-58cec1e31ed6\"\n",
    "        }\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"conversation/gen_title\", conversation_id)\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    data = {\n",
    "        \"message_id\": message_id\n",
    "    }\n",
    "    response = requests.post(url, headers=headers, data=json.dumps(data))\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "chat_list_resp = get_chat_list(backend_url, access_token, limit=1)\n",
    "conversation_id = chat_list_resp['items'][0]['id']\n",
    "resp = get_chat_by_id(backend_url, access_token, conversation_id)\n",
    "message_id = resp['current_node']\n",
    "resp = generate_chat_title(backend_url, access_token, conversation_id, message_id)\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Get Conversation Limit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'message_cap': 40.0,\n",
      " 'message_cap_window': 180.0,\n",
      " 'message_disclaimer': {'model-switcher': \"You've reached the GPT-4 cap, which \"\n",
      "                                          'gives all ChatGPT Plus users a '\n",
      "                                          'chance to try the model.\\n'\n",
      "                                          '\\n'\n",
      "                                          'Please check back soon.',\n",
      "                        'textarea': 'GPT-4 currently has a cap of 40 messages '\n",
      "                                    'every 3 hours.'}}\n"
     ]
    }
   ],
   "source": [
    "def get_conversation_limit(base_url:str, access_token:str):\n",
    "    \"\"\"Get conversation limit of gpt-4\n",
    "\n",
    "    Args:\n",
    "        base_url (str): base url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "    \n",
    "    Returns:\n",
    "        dict: conversation limit\n",
    "    \n",
    "    Rest API:\n",
    "        ### get conversation limit\n",
    "        GET http://{{host}}/public-api/conversation_limit\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(base_url, \"public-api/conversation_limit\")\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.get(url, headers=headers)\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "resp = get_conversation_limit(base_url, access_token)\n",
    "pprint(resp)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Send Data to Email"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'status': 'queued'}\n"
     ]
    }
   ],
   "source": [
    "def send_data_to_email(backend_url:str, access_token:str):\n",
    "    \"\"\"Send data to email\n",
    "\n",
    "    Args:\n",
    "        backend_url (str): backend url\n",
    "        access_token (str): access token at https://chat.openai.com/api/auth/session\n",
    "    \n",
    "    Returns:\n",
    "        dict: response\n",
    "    \n",
    "    Rest API:\n",
    "        ### export data send to email\n",
    "        POST http://{{host}}/backend-api/accounts/data_export\n",
    "        Authorization: {{bearer_token}}\n",
    "    \"\"\"\n",
    "    url = os.path.join(backend_url, \"accounts/data_export\")\n",
    "    headers = {\n",
    "        'Content-Type': 'application/json',\n",
    "        'Authorization': f'Bearer {access_token}'\n",
    "    }\n",
    "    response = requests.post(url, headers=headers)\n",
    "    return response.json()\n",
    "\n",
    "## Example\n",
    "resp = send_data_to_email(backend_url, access_token)\n",
    "pprint(resp)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
